#ifndef quantlib_single_fixed_leg_hpp
#define quantlib_single_fixed_leg_hpp

#include <ql/instruments/swap.hpp>
#include <ql/time/daycounter.hpp>
#include <ql/time/schedule.hpp>
#include <boost/optional.hpp>

namespace QuantLib {

    class IborIndex;

    class SingleFixedLeg : public Swap {
      public:
        enum Type { Receiver = -1, Payer = 1 };
        class arguments;
        class results;
        class engine;
        SingleFixedLeg(
            Type type,
            Real nominal,
            const Schedule& fixedSchedule,
            Rate fixedRate,
            const DayCounter& fixedDayCount);
        //! \name Inspectors
        //@{
        Type type() const;
        Real nominal() const;

        const Schedule& fixedSchedule() const;
        Rate fixedRate() const;
        const DayCounter& fixedDayCount() const;

        BusinessDayConvention paymentConvention() const;

        const Leg& fixedLeg() const;
        const Leg& floatingLeg() const;
        //@}

        //! \name Results
        //@{
        Real fixedLegBPS() const;
        Real fixedLegNPV() const;
        Rate fairRate() const;

        //@}
        // other
        void setupArguments(PricingEngine::arguments* args) const;
        void fetchResults(const PricingEngine::results*) const;
      private:
        void setupExpired() const;
        Type type_;
        Real nominal_;
        Schedule fixedSchedule_;
        Rate fixedRate_;
        DayCounter fixedDayCount_;
        BusinessDayConvention paymentConvention_;
        // results
        mutable Rate fairRate_;
        mutable Spread fairSpread_;
    };


    //! %Arguments for simple swap calculation
    class SingleFixedLeg::arguments : public Swap::arguments {
      public:
        arguments() : type(Receiver),
                      nominal(Null<Real>()) {}
        Type type;
        Real nominal;

        std::vector<Date> fixedResetDates;
        std::vector<Date> fixedPayDates;
        std::vector<Real> fixedCoupons;
       
		void validate() const;
    };

    //! %Results from simple swap calculation
    class SingleFixedLeg::results : public Swap::results {
      public:
        Rate fairRate;
        Spread fairSpread;
        void reset();
    };

    class SingleFixedLeg::engine : public GenericEngine<SingleFixedLeg::arguments,
                                                     SingleFixedLeg::results> {};


    // inline definitions

    inline SingleFixedLeg::Type SingleFixedLeg::type() const {
        return type_;
    }

    inline Real SingleFixedLeg::nominal() const {
        return nominal_;
    }

    inline const Schedule& SingleFixedLeg::fixedSchedule() const {
        return fixedSchedule_;
    }

    inline Rate SingleFixedLeg::fixedRate() const {
        return fixedRate_;
    }

    inline const DayCounter& SingleFixedLeg::fixedDayCount() const {
        return fixedDayCount_;
    }

    inline BusinessDayConvention SingleFixedLeg::paymentConvention() const {
        return paymentConvention_;
    }

    inline const Leg& SingleFixedLeg::fixedLeg() const {
        return legs_[0];
    }

    std::ostream& operator<<(std::ostream& out, SingleFixedLeg::Type t);

}

#endif
